package conchmusic.conchmusicclient.util;

import android.util.Log;

import org.json.JSONException;
import org.json.JSONObject;

import java.lang.reflect.Field;
import java.util.List;

import conchmusic.conchmusicclient.pojo.Album;
import conchmusic.conchmusicclient.pojo.Artist;
import conchmusic.conchmusicclient.pojo.Comment;
import conchmusic.conchmusicclient.pojo.Song;
import conchmusic.conchmusicclient.pojo.SongList;
import conchmusic.conchmusicclient.pojo.TimeStamps;
import conchmusic.conchmusicclient.pojo.UpdatedData;
import conchmusic.conchmusicclient.pojo.User;

/**
 * Utility class for building JSON Strings from bean objects.
 *
 * @author zhixu
 */
public class JsonBuilder {


	/**
	 * Build a JSONObject from a bean object.
	 * Should add new type strings in the switch block
	 * if fields of new types are to be added into a bean class.
	 * @param bean
	 * @return a JSONObject
	 */
	private JSONObject getBeanJsonObj(Object bean) {
		JSONObject resObj = new JSONObject();

		Field[] fields = bean.getClass().getDeclaredFields();
		for (Field field: fields) {
			field.setAccessible(true);
			try {
				String type = field.getType().getName();
				if ("serialVersionUID".equals(field.getName()))
					continue;
				switch (type) {
					case "java.util.List":
					case "java.lang.String":
					case "int":
					case "java.lang.Integer":
					case "long":
					case "java.lang.Long":
						resObj.put(field.getName(), field.get(bean));
						break;
					case "com.android.tools.fd.runtime.IncrementalChange":
						break;
					default:
						resObj.put(field.getName(), getBeanJsonObj(field.get(bean)));
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		return resObj;
	}
	/**
	 * Build a JSON string from a User object.
	 * @param user
	 * @return a JSON string
	 * @throws JSONException
	 */
	public String buildUser(User user) throws JSONException{
		JSONObject resObj = new JSONObject();
		resObj.put("type", "user");
		resObj.put("user", getBeanJsonObj(user));

		return resObj.toString();
	}

	/**
	 * Build a JSON string from a TimeStamp object.
	 * @param timeStamps
	 * @return a JSON string
	 * @throws JSONException
	 */
	public String buildTimeStamps(TimeStamps timeStamps) throws JSONException{
		JSONObject resObj = new JSONObject();
		resObj.put("type", "timeStamps");
		resObj.put("timeStamps", getBeanJsonObj(timeStamps));

		return resObj.toString();
	}

	/**
	 * Build a JSON string from a SongList object.
	 * @param songList
	 * @return a JSON string
	 * @throws JSONException
	 */
	public String buildSongList(SongList songList) throws JSONException{
		JSONObject resObj = new JSONObject();
		resObj.put("type", "songList");
		resObj.put("songList", getBeanJsonObj(songList));

		return resObj.toString();
	}

	/**
	 * Build a JSON string from a UpdatedData object
	 * @param updatedData
	 * @return a JSON string
	 * @throws JSONException
	 */
	public String buildUpdatedData(UpdatedData updatedData) throws JSONException{
		JSONObject resObj = new JSONObject();
		resObj.put("type", "updatedData");
		resObj.put("updatedData", getBeanJsonObj(updatedData));

		return resObj.toString();
	}

	/**
	 * Build a ValidInfo format JSON string from a message string.
	 * The result JSON string has two fields: a "type" field with "validInfo" value
	 * and a "msg" field with string value from "msg" parameter.
	 * @param msg
	 * @return a JSON string
	 * @throws JSONException
	 */
	public String buildValidInfo(String msg) throws JSONException{
		JSONObject resObj = new JSONObject();
		resObj.put("type", "validInfo");
		resObj.put("msg", msg);

		return resObj.toString();
	}


	/**
	 * Build a InvalidInfo format JSON string from a message string.
	 * The result JSON string has two fields: a "type" field with "invalidInfo" value
	 * and a "msg" field with string value from "msg" parameter.
	 * @param msg
	 * @return a JSON string
	 * @throws JSONException
	 */
	public String buildInvalidInfo(String msg) throws JSONException{
		JSONObject resObj = new JSONObject();
		resObj.put("type", "invalidInfo");
		resObj.put("msg", msg);

		return resObj.toString();
	}

	/**
	 * Build a JSON string from a Artist object.
	 * @param artist
	 * @return a JSON string
	 * @throws JSONException
	 */
	public String buildArtist(Artist artist) throws JSONException{
		JSONObject resObj = new JSONObject();
		resObj.put("type", "artist");
		resObj.put("artist", getBeanJsonObj(artist));

		return resObj.toString();
	}

	/**
	 * Build a JSON string from a Album object.
	 * @param album
	 * @return a JSON string
	 * @throws JSONException
	 */
	public String buildAlbum(Album album) throws JSONException{
		JSONObject resObj = new JSONObject();
		resObj.put("type", "album");
		resObj.put("album", getBeanJsonObj(album));

		return resObj.toString();
	}

	/**
	 * Build a JSON string from a Comment object.
	 * @param comment
	 * @return a JSON string
	 * @throws JSONException
	 */
	public String buildComment(Comment comment) throws JSONException{
		JSONObject resObj = new JSONObject();
		resObj.put("type", "comment");
		resObj.put("comment", getBeanJsonObj(comment));

		return resObj.toString();
	}

	/**
	 * Build a JSON string from a Comment list.
	 * @param comments
	 * @return a JSON string.
	 * @throws JSONException
	 */
	public String buildComments(List<Comment> comments) throws JSONException{
		JSONObject resObj = new JSONObject();
		resObj.put("type", "comments");
		resObj.put("comments", comments);

		return resObj.toString();
	}

	/**
	 * Build a JSON string from a Song list.
	 * @param songs
	 * @return a JSON string
	 * @throws JSONException
	 */
	public String buildSongs(List<Song> songs) throws JSONException{
		JSONObject resObj = new JSONObject();
		resObj.put("type", "songs");
		resObj.put("songs", songs);

		return resObj.toString();
	}
}